package com.kmxd.ams.core.util;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.google.common.base.Function;
import com.google.common.collect.ComparisonChain;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Ordering;
import com.kmxd.ams.core.common.enums.FieldOrderTypeEnum;
import lombok.Data;

import java.util.Comparator;
import java.util.Date;
import java.util.List;

/**
 * 排序通用工具
 *
 * @author nickbi
 */
public interface SortUtils {

  /**
   * 通过排序设置，生成数据排序条件
   *
   * @param orderList 排序信息列表
   * @param <T> 排序数据类型
   * @return 排序信息
   */
  static <T> Comparator<T> buildSort(List<FieldOrder> orderList) {
    return (document, t1) -> {
      ComparisonChain start = ComparisonChain.start();
      for (FieldOrder fieldOrder : orderList) {
        String orderFieldCode = fieldOrder.getOrderFieldCode();
        // 准换字段名称为驼峰
        String fieldCode =
            StringUtils.isCamel(orderFieldCode)
                ? orderFieldCode
                : StringUtils.underlineToCamel(orderFieldCode);

        Object fieldValue = BeanUtil.getFieldValue(document, fieldCode);
        Object fieldValue1 = BeanUtil.getFieldValue(t1, fieldCode);
        FieldOrderTypeEnum orderType = FieldOrderTypeEnum.convert(fieldOrder.getOrderType());
        Ordering ordering =
            orderType.equals(FieldOrderTypeEnum.ASC)
                ? Ordering.natural().nullsFirst()
                : Ordering.natural().reverse().nullsLast();
        if (fieldValue instanceof Integer) {
          start = start.compare((Integer) fieldValue, (Integer) fieldValue1, ordering);
          continue;
        }
        if (fieldValue instanceof Long) {
          start = start.compare((Integer) fieldValue, (Integer) fieldValue1, ordering);
          continue;
        }
        if (fieldValue instanceof Double) {
          start = start.compare((Double) fieldValue, (Double) fieldValue1, ordering);
          continue;
        }
        if (fieldValue instanceof Date) {
          start = start.compare((Date) fieldValue, (Date) fieldValue1, ordering);
          continue;
        }
        if (fieldValue instanceof Boolean) {
          start = start.compare((Boolean) fieldValue, (Boolean) fieldValue1, ordering);
          continue;
        }
        if (fieldValue instanceof String) {
          start = start.compare((String) fieldValue, (String) fieldValue1, ordering);
        }
      }
      return start.result();
    };
  }

  @Data
  class FieldOrder {
    private String orderFieldCode;
    private String orderType;
  }

  /**
   * 通过ids对列表进行排序
   *
   * @param sourceList 原数据列表
   * @param ids 参照ids
   * @param function 列表属性方法
   * @param <E> 列表类型
   * @return 排序结果
   */
  static <T, E extends T, F> List<E> sortList(
      List<F> sourceList, List<T> ids, Function<F, ? extends T> function) {
    Ordering<F> ordering = Ordering.explicit(ids).onResultOf(function);
    return (ImmutableList<E>) ordering.immutableSortedCopy(sourceList);
  }

  /**
   * 通过ids对列表进行排序
   *
   * @param sourceList 原数据列表
   * @param ids 参照ids
   * @param function 列表属性方法
   * @param <E> 列表类型
   * @return 排序结果
   */
  static <T, E extends T, F> List<E> sortWithIds(
      List<F> sourceList, String ids, Function<F, ? extends Long> function) {
    Ordering<F> ordering = Ordering.explicit(IdUtil.splitSortList(ids)).onResultOf(function);
    return (ImmutableList<E>) ordering.immutableSortedCopy(sourceList);
  }
}
